<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue'
import { ElMessage, type FormRules } from 'element-plus'
import { hasSpaceWithStartAndEnd } from '@/utils/validate'
import ImageUploader from '@/plugins/stratocirri-plus/components/image-uploader/ImageUploader.vue'
import { useFileDialog } from '@vueuse/core'
import { uploadFile } from '@/utils/uploader'
import { getModelInfo } from '@/api/interface/museum/model'

interface Props {
  data?: Record<string, any> | never | null
  status?: any
}

const props = withDefaults(defineProps<Props>(), {
  data: null,
  status: 'add'
})

const disabled = computed(() => {
  return props.status === 'view'
})

const fullscreenLoading = ref(false)
const loading = ref(false)

const formRef = ref()

const form = reactive<Record<string, any>>({})

const rules = reactive<FormRules>({
  modelName: [
    { required: true, message: '模型名称不能为空!', trigger: 'blur' },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (value) {
          if (hasSpaceWithStartAndEnd(value)) {
            callback(new Error('模型名称首尾不能有空格!'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ],
  modelImg: [{ required: true, message: '请上传预览图', trigger: 'change' }],
  modelUrl: [{ required: true, message: '请上传3D模型', trigger: 'change' }]
})

const initForm = () => {
  if (props.status !== 'add') {
    loading.value = true
    getModelInfo({
      id: props.data?.id
    })
      .then((res: any) => {
        Object.keys(res).forEach((key: string) => {
          form[key] = res[key]
        })
      })
      .finally(() => {
        loading.value = false
      })
  }
}
initForm()

const imageChange = (val: string) => {
  form.modelImg = val
}

const { files, open, reset } = useFileDialog({
  multiple: false,
  accept: '.glb'
})

const callOpen = () => {
  open()
}

const removeFile = () => {
  if (files.value) {
    reset()
  } else {
    form.modelUrl = null
  }
}

watch(
  files,
  (newVal) => {
    if (newVal) {
      // 上传
      fullscreenLoading.value = true
      const file = newVal[0]
      if (!form.modelName) {
        form.modelName = `${file.name}`.substring(0, file.name.length - 4)
      }
      uploadFile({ file }, 0)
        .then((res: any) => {
          form.modelUrl = res.url
          ElMessage({
            type: 'success',
            message: '上传成功'
          })
        })
        .catch(() => {
          reset()
        })
        .finally(() => {
          fullscreenLoading.value = false
        })
    } else {
      // 删除
      form.modelUrl = null
    }
  },
  {
    deep: true
  }
)

const formatForm = () => {
  const result: Record<string, any> = {}
  Object.keys(form).forEach((key: string) => {
    result[key] = form[key]
  })
  return result
}

const submitForm = () => {
  return new Promise<any>((resolve) => {
    formRef.value.validate((valid: boolean) => {
      let res: any = null
      if (valid) {
        res = formatForm()
      }
      resolve(res)
    })
  })
}

defineExpose({
  submitForm
})
</script>

<template>
  <div v-loading.fullscreen="fullscreenLoading" v-loading="loading" class="form-wrapper">
    <el-form ref="formRef" :model="form" :rules="rules" label-position="top" label-width="120px">
      <el-form-item label="模型名称：" prop="modelName">
        <el-input v-model="form.modelName" type="text" placeholder="请输入模型名称" maxlength="20" :disabled="disabled" />
      </el-form-item>
      <el-form-item label="预览图：" prop="modelImg">
        <ImageUploader :default-url="form.modelImg" :limit-file-size="2" @image-change="imageChange" :disabled="disabled"></ImageUploader>
      </el-form-item>
      <el-form-item label="3D模型：" prop="modelUrl">
        <div class="form-item-model-container">
          <template v-if="!disabled">
            <div v-if="!form.modelUrl" class="model-edit-text" @click="callOpen">上传模型</div>
            <div v-else class="model-edit-text delete" @click="removeFile">删除模型</div>
          </template>
          <div v-if="form.modelUrl">
            <model-viewer :src="form.modelUrl" style="width: 100%; min-width: 500px; height: 500px" camera-controls></model-viewer>
          </div>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>

<style lang="scss" scoped>
.form-wrapper {
  padding-left: 10px;
  .form-item-model-container {
    @include rect(100%, 100%);
    .model-edit-text {
      width: fit-content;
      cursor: pointer;
      text-decoration: underline;
      text-underline-offset: 2px;
      color: var(--theme-color);
      &.delete {
        color: var(--theme-color-danger);
      }
    }
  }
}
</style>
